#include <iostream>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <algorithm>
#include <cassert>

#include "contact.hpp"

void *lMF(void *obj)
{
	contact *ptr = reinterpret_cast<contact *>(obj);
	return ptr->readMessage();
}

contact::contact(std::string h, QString remoteNick, int fd, QString hostNick)
{
	host_name = h;
	sockfd 	  = fd;
	hNick	  = hostNick;
	rNick 	  = remoteNick;

	chtWin	  = new QWidget;
	recMess   = new QTextBrowser;
	sendMess  = new QLineEdit;
	chtLayout = new QVBoxLayout;

	chtWin->setWindowTitle(remoteNick);	
	chtLayout->addWidget(recMess);
	chtLayout->addWidget(sendMess);
	chtWin->setLayout(chtLayout);


	if(fd == -2)
		connectTo();
	setText(rNick);

	pthread_create(&p_read, NULL, lMF, this);
}

void contact::connectTo()
{
	int portno = 6565;
	sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
	sockaddr_in serv_addr;

	if (sockfd < 0) {
		std::cerr << "Error opening socket" << std::endl;
		return;
	}
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	inet_pton(AF_INET, host_name.c_str(), &serv_addr.sin_addr);
	serv_addr.sin_port = htons(portno);

	int n = ::connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr));
	if( n < 0) {
		std::cerr << "ERROR connecting" << std::endl;
		return;
	}

	int length = ((hNick.toStdString()).length()) + 1;
	char* buff = new char[length];
	assert(0 != buff);

	strcpy(buff, (char*)((hNick.toStdString()).c_str()));
	buff[length - 1] = '\0';
	n = ::write(sockfd, buff, length);
	if(n < 0)
		std::cout << "Can't send Nick Name\n";

	char rbuff[255];
	n = ::read(sockfd, rbuff, 255);
	if(n < 0)
		std::cout << "Error reading from socket\n";
	rNick = rbuff;

}

void contact::insertMess()
{
	recMess->insertPlainText("U: " + sendMess->text() + '\n');
	QTextCursor cr = recMess->textCursor();
       	cr.movePosition(QTextCursor::End);
	recMess->setTextCursor(cr);
	int length = ((sendMess->text()).toStdString()).length() + 1;
	char* buffer = new char[length];
	assert(0 != buffer);

	strcpy(buffer, (char*)(((sendMess->text()).toStdString()).c_str()));
	buffer[length - 1] = '\0';

	int n = ::write(sockfd, buffer, length);
	if(n < 0)
		std::cout << "Can't write to socket\n";
	sendMess->setText("");
}

void* contact::readMessage()
{
	void *retval = NULL;
	char buffer[255];
	while(true){
		memset(buffer, 0, sizeof(buffer));
		int n = ::read(sockfd, buffer, 255);
		if(n < 0) {
			std::cerr << "ERROR reading from socket" << std::endl;
			return retval;
		}
		assert(0 != recMess);
		recMess->insertPlainText(rNick + (char*)": " +
				(QString)buffer + '\n');
		QTextCursor cr = recMess->textCursor();
		cr.movePosition(QTextCursor::End);
		recMess->setTextCursor(cr);
	}
	return retval;
}

